﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectTest
{
    public class Container : Dictionary<Type, Type>
    {

        public T Resolve<T>() where T : class
        {
            return Resolve(typeof (T)) as T;
        }

        public void RegisterType<T>() where T : class
        {
            RegisterType(typeof (T));
        }

        private object Resolve(Type interfaceType)
        {
            if (!ContainsKey(interfaceType))
            {
                return null;
            }

            var implType = this[interfaceType];
            var constructorInfo = implType.GetConstructors();
            if (constructorInfo.Length > 1)
            {
                throw new Exception(implType.FullName + "类只能有一个构造函数");
            }

            var parasInfo = constructorInfo[0].GetParameters();

            //无参构造
            if (parasInfo.Length <= 0)
                return Activator.CreateInstance(implType);

            //有参数
            var args = new object[parasInfo.Length];
            for (var i = 0; i < parasInfo.Length; i++)
            {
                args[i] = Resolve(parasInfo[i].ParameterType);
            }

            return Activator.CreateInstance(implType, args);
        }

        private void RegisterType(Type type)
        {
            //获取类实现的接口
            var interfaces = type.GetInterfaces();
            //如果没有实现接口
            if (interfaces.Length == 0)
            {
                Add(type,type);
                return;;
            }

            if (interfaces.Length > 1)
            {
                throw new NotImplementedException(type.FullName + "类实现了多个接口，要求一个类只能实现一个接口");
            }
            //缓存接口和类
            Add(interfaces[0], type);
        }



        public void RegisterAssemblyTypes(Assembly assembly, Func<Type, bool> filter)
        {
            //获取public 类
            var types = assembly.GetExportedTypes().Where(t => t.IsClass);
            //过滤
            if (filter != null)
            {
                types = types.Where(filter).ToArray();
            }

            foreach (var type in types)
            {
                RegisterType(type);
            }
        }
    }
}
